package com.xbongbong.workflow.service.strategy.node.impl;

import com.alibaba.fastjson.JSON;
import com.xbongbong.paas.constant.MessageConstant;
import com.xbongbong.paas.constant.PaasConstant;
import com.xbongbong.paas.domain.entity.PaasFormSubDataEntity;
import com.xbongbong.paas.domain.entity.ext.PaasFormDataEntityExt;
import com.xbongbong.sys.help.PackageHelp;
import com.xbongbong.paas.toolbox.exception.XbbException;
import com.xbongbong.paas.toolbox.util.CollectionsUtil;
import com.xbongbong.pro.enums.PackageTypeEnum;
import com.xbongbong.pro.formdata.pojo.SaasNeedRedundantAttrPojo;
import com.xbongbong.saas.constant.BasicConstant;
import com.xbongbong.workflow.domain.entity.WorkflowNodeEntity;
import com.xbongbong.workflow.enums.WorkflowNodeTypeEnum;
import com.xbongbong.paas.config.enums.WorkflowTaskLogStatusEnum;
import com.xbongbong.paas.exception.WorkflowException;
import com.xbongbong.workflow.pojo.FilterCondition;
import com.xbongbong.workflow.pojo.FlowData;
import com.xbongbong.workflow.pojo.FlowDatas;
import com.xbongbong.paas.pojo.workflow.WorkflowDataPojo;
import com.xbongbong.workflow.pojo.WorkflowProcessResultPojo;
import com.xbongbong.workflow.pojo.WorkflowTransferPOJO;
import com.xbongbong.workflow.pojo.nodes.ObtainMultiDataNode;
import com.xbongbong.workflow.service.help.WorkflowDataNodeHelp;
import com.xbongbong.workflow.service.strategy.node.AbstractWorkflowNodeStrategy;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;

/**
 * 获取多条数据节点
 * @author 魏荣杰
 *
 */
@Service
public class WorkflowNodeMultiDataStrategy extends AbstractWorkflowNodeStrategy {

    private static final Logger LOGGER = LoggerFactory.getLogger(WorkflowNodeMultiDataStrategy.class);


    @Resource
    private WorkflowDataNodeHelp workflowDataNodeHelp;
    @Resource
    private PackageHelp packageHelp;


    @Override
    public String type() {
        return WorkflowNodeTypeEnum.MULTI_DATA_NODE.getName();
    }

    @Override
    public void before(WorkflowTransferPOJO workflowTransferPOJO) {
        super.before(workflowTransferPOJO);
    }

    @Override
    public WorkflowProcessResultPojo process(WorkflowTransferPOJO workflowTransferPOJO, WorkflowNodeEntity workflowNodeEntity, Long lastNodeId, SaasNeedRedundantAttrPojo saasNeedRedundantAttrPojo) {
        try {
            String corpid = workflowTransferPOJO.getCorpid();
            FlowDatas flowDatas = workflowTransferPOJO.getFlowDatas() == null ? new FlowDatas() : workflowTransferPOJO.getFlowDatas();
            Map<String, FlowData> nodeIdMap = Objects.isNull(flowDatas) || flowDatas.getNodeIdMap() == null ? new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY) : flowDatas.getNodeIdMap();
            FlowData flowData = new FlowData(workflowNodeEntity.getFormId(), workflowNodeEntity.getAppId(), workflowNodeEntity.getMenuId(),
                    workflowNodeEntity.getSaasMark(), workflowNodeEntity.getBusinessType(), new ArrayList<>(), new ArrayList<>());
            nodeIdMap.put(workflowNodeEntity.getId().toString(), flowData);
            flowDatas.setNodeIdMap(nodeIdMap);
            workflowTransferPOJO.setFlowDatas(flowDatas);
            Integer feeType = packageHelp.getFeeType(corpid);
            if (!Objects.equals(PackageTypeEnum.ULTIMATE.getType(), feeType)) {
                logger(workflowTransferPOJO, workflowNodeEntity, WorkflowTaskLogStatusEnum.PASS, new WorkflowException(MessageConstant.WORKFLOW_NODE_VERSION_NOT_SUPPORT));
                return new WorkflowProcessResultPojo(true, false);
            }

            nodeIdMap.put(workflowNodeEntity.getId().toString(), flowData);
            ObtainMultiDataNode obtainMultiDataNode = JSON.parseObject(workflowNodeEntity.getConfigData(), ObtainMultiDataNode.class);
            if (Objects.nonNull(obtainMultiDataNode)) {
                List<FilterCondition> filterCondition = obtainMultiDataNode.getFilterCondition();
                if (CollectionsUtil.isEmpty(filterCondition)) {
                    return new WorkflowProcessResultPojo(true, false);
                }
                WorkflowDataPojo workflowDataPojo = workflowDataNodeHelp.getDataList(obtainMultiDataNode.getEditedData(), workflowNodeEntity, filterCondition, workflowTransferPOJO,
                        obtainMultiDataNode.getOrderField(), obtainMultiDataNode.getOrder(), PaasConstant.PAGE_NUM);
                // 根据条件去查数据
                List<PaasFormDataEntityExt> dataList = workflowDataPojo.getDataList();
                // 根据条件去查子数据
                List<PaasFormSubDataEntity> subDataList = workflowDataPojo.getSubDataList();
                // TODO 审批不允许编辑如何处理
                if (CollectionsUtil.isEmpty(dataList)) {
                    if (Objects.equals(obtainMultiDataNode.getNoDataEvent(), BasicConstant.ONE)) {
                        nodeIdMap.put(workflowNodeEntity.getId().toString(), flowData);
                        flowDatas.setNodeIdMap(nodeIdMap);
                        workflowTransferPOJO.setFlowDatas(flowDatas);
                        // 未获取到数据时，继续执行或执行查找结果分支
                        logger(workflowTransferPOJO, workflowNodeEntity, WorkflowTaskLogStatusEnum.PASS, new WorkflowException(MessageConstant.WORKFLOW_NODE_PASS_NO_DATA));
                        return new WorkflowProcessResultPojo(true, false);
                    } else if (Objects.equals(obtainMultiDataNode.getNoDataEvent(), BasicConstant.TWO)) {
                        // 中止流程
                        nodeIdMap.put(workflowNodeEntity.getId().toString(), flowData);
                        flowDatas.setNodeIdMap(nodeIdMap);
                        workflowTransferPOJO.setFlowDatas(flowDatas);
                        // 未获取到数据中止流程时
                        logger(workflowTransferPOJO, workflowNodeEntity, WorkflowTaskLogStatusEnum.SUSPEND, new WorkflowException(MessageConstant.WORKFLOW_NODE_SUSPEND_NO_DATA));
                        return new WorkflowProcessResultPojo(false, false, true);
                    }else {
                        nodeIdMap.put(workflowNodeEntity.getId().toString(), flowData);
                        flowDatas.setNodeIdMap(nodeIdMap);
                        workflowTransferPOJO.setFlowDatas(flowDatas);
                    }
                } else if (dataList.size() > PaasConstant.LIMIT_MAX_NUM) {
                    if (Objects.equals(obtainMultiDataNode.getExceedLimitDataEvent(), BasicConstant.ONE)) {
                        dataList = dataList.subList(0, PaasConstant.LIMIT_MAX_NUM);
                        List<Long> dataIdList = new ArrayList<>();
                        List<Long> subDataIdList = new ArrayList<>();
                        dataList.forEach(item->dataIdList.add(item.getDataId()));
                        flowData.setIds(dataIdList);
                        subDataList.forEach(item->{
                            if (dataIdList.contains(item.getDataId())) {
                                subDataIdList.add(item.getId());
                            }
                        });
                        flowData.setIds(dataIdList);
                        flowData.setSubDataIdIn(subDataIdList);
                        nodeIdMap.put(workflowNodeEntity.getId().toString(), flowData);
                        flowDatas.setNodeIdMap(nodeIdMap);
                        workflowTransferPOJO.setFlowDatas(flowDatas);
                        // 超过限制数量时仅执行限制内数据
                        logger(workflowTransferPOJO, workflowNodeEntity, WorkflowTaskLogStatusEnum.PASS, new WorkflowException(MessageConstant.WORKFLOW_NODE_PASS_MAX_DATA));
                        return new WorkflowProcessResultPojo(true, false);
                    }else if (Objects.equals(obtainMultiDataNode.getExceedLimitDataEvent(), BasicConstant.TWO)) {
                        // 跳过并继续执行
                        List<Long> dataIdList = new ArrayList<>();
                        dataList.forEach(item->dataIdList.add(item.getDataId()));
                        flowData.setIds(new ArrayList<>());
                        nodeIdMap.put(workflowNodeEntity.getId().toString(), flowData);
                        flowDatas.setNodeIdMap(nodeIdMap);
                        workflowTransferPOJO.setFlowDatas(flowDatas);
                        // 获取数据超过50条数量限制，跳过，继续执行流程
                        logger(workflowTransferPOJO, workflowNodeEntity, WorkflowTaskLogStatusEnum.PASS, new WorkflowException(MessageConstant.WORKFLOW_NODE_PASS_MAX_DATA_IGNORE));
                        return new WorkflowProcessResultPojo(true, false);
                    }else if (Objects.equals(obtainMultiDataNode.getExceedLimitDataEvent(), BasicConstant.THREE)) {
                        // 中止流程
                        flowData.setIds(new ArrayList<>());
                        nodeIdMap.put(workflowNodeEntity.getId().toString(), flowData);
                        flowDatas.setNodeIdMap(nodeIdMap);
                        workflowTransferPOJO.setFlowDatas(flowDatas);
                        // 超过限制数量时中止流程
                        logger(workflowTransferPOJO, workflowNodeEntity, WorkflowTaskLogStatusEnum.SUSPEND, new WorkflowException(MessageConstant.WORKFLOW_NODE_SUSPEND_MAX_DATA));
                        return new WorkflowProcessResultPojo(false, false, true);
                    } else {
                        nodeIdMap.put(workflowNodeEntity.getId().toString(), flowData);
                        flowDatas.setNodeIdMap(nodeIdMap);
                        workflowTransferPOJO.setFlowDatas(flowDatas);
                    }
                } else {
                    List<Long> dataIdList = new ArrayList<>();
                    List<Long> subDataIdList = new ArrayList<>();
                    dataList.forEach(item->dataIdList.add(item.getDataId()));
                    flowData.setIds(dataIdList);
                    subDataList.forEach(item->{
                        subDataIdList.add(item.getId());
                    });
                    flowData.setSubDataIdIn(subDataIdList);
                    nodeIdMap.put(workflowNodeEntity.getId().toString(), flowData);
                    flowDatas.setNodeIdMap(nodeIdMap);
                    workflowTransferPOJO.setFlowDatas(flowDatas);
                    logger(workflowTransferPOJO, workflowNodeEntity, WorkflowTaskLogStatusEnum.PASS, new WorkflowException(MessageConstant.WORKFLOW_NODE_PASS_OBTAINED_DATA, dataList.size()));
                    return new WorkflowProcessResultPojo(true, false);
                }
            }
        } catch (WorkflowException e) {
            logger(workflowTransferPOJO, workflowNodeEntity, WorkflowTaskLogStatusEnum.FAIL, e);
            return new WorkflowProcessResultPojo(false, false);
        } catch (XbbException e) {
            WorkflowException workflowException = new WorkflowException(e.getMsg());
            logger(workflowTransferPOJO, workflowNodeEntity, WorkflowTaskLogStatusEnum.FAIL, workflowException);
            LOGGER.error("WorkflowNodeMultiDataStrategy.process error", e);
            return new WorkflowProcessResultPojo(false, false);
        } catch (Exception e) {
            WorkflowException workflowException = new WorkflowException(e.getMessage());
            logger(workflowTransferPOJO, workflowNodeEntity, WorkflowTaskLogStatusEnum.FAIL, workflowException);
            LOGGER.error("WorkflowNodeMultiDataStrategy.process error", e);
            return new WorkflowProcessResultPojo(false, false);
        }
        return new WorkflowProcessResultPojo(true, false);
    }





    @Override
    public void after(WorkflowTransferPOJO workflowTransferPOJO, WorkflowNodeEntity workflowNodeEntity) {
        super.after(workflowTransferPOJO, workflowNodeEntity);
    }

    @Override
    public void check() {
        super.check();
    }

    @Override
    public void logger(WorkflowTransferPOJO workflowTransferPOJO, WorkflowNodeEntity nodeEntity, WorkflowTaskLogStatusEnum workflowTaskLogStatusEnum, WorkflowException workflowException) {
        super.logger(workflowTransferPOJO, nodeEntity, workflowTaskLogStatusEnum, workflowException);
    }
}
